package bandi.osgi.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import xmlwriter.XMLCreatorExample;

import bandi.osgi.dalservice.service.DALService;
import bandi.osgi.gpsdata.ClientMessage;
import bandi.osgi.gpsdata.GpsGGAMessage;

public class Server {

	private ServerSocket sock;

	private final int port = 8989;

	private boolean active = true;

	private XMLCreatorExample xce;

	private List<ClientMessage> messages;

	private boolean signal1, signal2;

	private DALService ds;
	private Thread th=new Thread();
	private Runnable r1;

	public Server(XMLCreatorExample _xce, DALService _ds) {
		super();
		xce = _xce;
		ds = _ds;
		signal1 = true;
		signal2 = false;
		messages = new ArrayList<ClientMessage>();
		Ofline wt = new Ofline();
		Thread t = new Thread(wt);
		t.start();
	}

	
	public void start() {
		active = true;
		Socket s;
		System.out.println("server> Server started on port " + port);
		
		try {
			sock = new ServerSocket(port);
			WriterThread wt = new WriterThread();
			Thread t = new Thread(wt);
			t.start();
			while (active) {
				s = sock.accept();
				System.out.println("server> new client message:");
				ServerThread mth = new ServerThread(s);
				mth.run();
			}
			System.out.println("server> Server has stopped listening.");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void stop() throws IOException {
		active = false;
		sock.close();
		System.out.println("server> Server has closed the socket");
		System.out.println("server> Server has stopped.");
	}

	
	
	class WriterThread implements Runnable {

		public void run() {
			while (active) {
				System.out.println("waiting to write...");
				try {
					Thread.sleep(4000);
					//xce.offline();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("waiting for signal..");
				while (signal1) {
					// wait for the other thread to write data
				}
				signal2 = true;
				System.out.println("starting writing..");//System.out.print(messages.size());
				if (messages.size() > 0) {
					messages.remove(1);
					 //messages.clear();
					System.out.println("stopped writing..");
				} else {
					System.out.println("nothing was written: list empty..");
				}

				signal2 = false;

			}

		}

	}

	class ServerThread implements Runnable {
		private Socket socket;

		public ServerThread(Socket s1) {
			socket = s1;
		}

		synchronized public void run() {
			ObjectInputStream oin;
			try {
				oin = new ObjectInputStream(socket.getInputStream());
				Object[] obj = new Object[3];
				int i = 0;
				boolean b = true;
				while (i != 3) {
					obj[i] = oin.readObject();
					i++;
				}
				if (((String) obj[2]).equals("STOP_SERVER")) {
					b = false;
					active = false;
				}
				if (b) {
					long userID = Long.parseLong(obj[0].toString());
					long deviceID = Long.parseLong(obj[1].toString());
					GpsGGAMessage gpsGGAMessage;
					String str = (String) obj[2];
					gpsGGAMessage = new GpsGGAMessage(str);
					System.out.println("server> received from client: \n"
							+ gpsGGAMessage.phoneOut());
					ClientMessage cm = new ClientMessage(deviceID, gpsGGAMessage, userID);
					
					boolean add = true;
					while (signal2) {
						// wait
					}
					signal1 = true;
					if (messages.size() > 0) {
						for (int j = 0; j < messages.size(); j++) {
							if (cm.getDeviceID() == messages.get(j).getDeviceID()
									&& cm.getUserID() == messages.get(j).getUserID()) {
								add = false;
								cm.setDevice(messages.get(j).getDevice());
								cm.setUser(messages.get(j).getUser());
								messages.remove(j);
								messages.add(cm);
								xce.updateFile(messages);
							}
						}
					}
					if (add) {
						cm.setDevice(ds.getDeviceService().getDevice(cm.getDeviceID()));
						cm.setUser(ds.getUserService().getUser(cm.getUserID()));
						messages.add(cm);
					}
					signal1 = false;
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}

		}
	}
	class Ofline implements Runnable {

		public void run() {
			while (active) {
				
				try {
					Thread.sleep(10000);
					xce.offline();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
	}
	}
}
